#include "entity.h"

#define ENABLE_UNIT_TEST 1
#define DEBUG_LEVEL 2

Entity::Entity(void)
{
	atEnd=true;
	atNull=true;
	iter_cid=0;
	iter_sid=0;
}


InfoSet * Entity::i(EInfoId iid)
{
	return NULL;
}


InfoSet * Entity::addInfoSet(EInfoId iid)
{
	/* ------------ CLASSLIST VECTOR -------------- */
	/* expand classlist if necessary */
	unsigned int cid = iidClassNumber(iid);
	if (infolist.size() < cid+1)
	{
		/* new list item needed. resize vector */
		infolist.resize(cid+1);
	}
	/* get sublist from classlists */
	TInfoVector& sublist = infolist[cid];

	/* ------------- SUBLIST VECTOR ------------------ */
	/* expand sublist if necessary */
	unsigned int sid = iidSubNumber(iid);
	if (sublist.size() < sid+1)
	{
		/* new list item needed. resize vector */
		unsigned int oldsize = sublist.size();
		/* fill the list with new data */
		for(unsigned int i=oldsize;i<sublist.size();i++)
		{
			InfoSet new_iset((EInfoId)iid_Number(sid, i));
			sublist.push_back(new_iset);
		}
	}
	/* update iterator variables */
	if ((!atNull) && (cid > iter_cid || (cid == iter_cid && sid > iter_sid)))
	{
		atEnd = false;
	}
	/* return pointer to the stuff */
	return &(sublist[sid]);			
}


InfoSet * Entity::firstInfoSet()
{ /* goto first non-empty infoset; NULL if empty list */
	if (infolist.size() == 0)
	{
		atNull = true;
		atEnd = true;
		return NULL;
	}
	/* try first */
	iter_cid = 0;
	iter_sid = 0;
	atNull = false;
	atEnd = false;
	TInfoVector& iv = infolist[0];
	if (!iv[0].isEmpty())
	{
		/* found first */
		return &(iv[0]);
	}
	else {
		/* seek for further isets... */
		return nextInfoSet();
	}
}


InfoSet * Entity::nextInfoSet()
{
	unsigned int old_iter_cid = iter_cid, old_iter_sid = iter_sid;
	/* trivial cases */
	if (atNull || atEnd)
		return NULL;
	/* goto next non-empty infoset; NULL if not found */
	for(;;)
	{
		iter_sid++;
		if (iter_sid >= infolist[iter_cid].size())
		{
			iter_sid=0;
			iter_cid++;
			if (iter_cid >= infolist.size())
			{
				/* scrolled to end of list and nothing found! */
				atEnd = true;
				iter_cid = old_iter_cid;
				iter_sid = old_iter_sid;
				return NULL;
			}
		}
		/* test (iter_cid,iter_sid) */
		if (!infolist[iter_cid][iter_sid].isEmpty())
		{
			/* found the next one! */
			return &(infolist[iter_cid][iter_sid]);			
		}
	}
}


bool Entity::endOfInfoSets()
{/* = cannot get next infoset; at last infoset or empty list */
	return atEnd;
}


void Entity::toStream(std::ostream& os, unsigned int indent, ESerializationType sertype)
{
	os << "Entity info {\n";
	/* iterate throught all infosets and call toStream for them */
	for(InfoSet *is = firstInfoSet(); !endOfInfoSets(); is = nextInfoSet())
		is->toStream(os, indent+2, sertype);
	os << "}" << std::endl;
}

std::ostream& operator<<(std::ostream& os, Entity& e)
{
	e.toStream(os, 0, stFull);
	return os;
}




/* ------------------------- UNIT TEST PROGRAM --------------------------------- */

#if (ENABLE_UNIT_TEST >= 1)
/* test program for InfoSet-class */

int main(void)
{
	Info i1(true), i2(15), i3(4.332f); i2.source = isSense;
	std::cout << i1 << i2 << i3 << std::endl;

    InfoSet iset(i_spa_Position);
	iset.addInfo(i1);
	iset.addInfo(i2);
	iset.addInfo(i3);

	std::cout << iset << std::endl;

	std::cout << "-------ENTITY TEST SECTION-------\n";

	Entity e;
	std::cout << e;
	
	return 0;
}

#endif
